package com.yc.cloud.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.admin.dto.request.HwCameraSnapshotStrategyCreateReqDTO;
import com.yc.cloud.admin.dto.request.HwCameraSnapshotStrategyUpdateReqDTO;
import com.yc.cloud.admin.dto.request.StrategyTimeslotBindReqDTO;
import com.yc.cloud.admin.dto.request.StrategyTimeslotUnbindReqDTO;
import com.yc.cloud.admin.vo.HwCameraSnapshotStrategyVo;
import com.yc.cloud.admin.vo.HwCameraTimeSlotVo;
import com.yc.cloud.entity.HwCameraSnapshotRelation;
import com.yc.cloud.entity.HwCameraSnapshotStrategy;
import com.yc.cloud.entity.HwCameraSnapshotTimeslotRelation;
import com.yc.cloud.entity.HwCameraTimeSlot;
import com.yc.cloud.mapper.HwCameraSnapshotRelationMapper;
import com.yc.cloud.mapper.HwCameraSnapshotStrategyMapper;
import com.yc.cloud.mapper.HwCameraSnapshotTimeslotRelationMapper;
import com.yc.cloud.mapper.HwCameraTimeSlotMapper;
import com.yc.cloud.admin.service.HwCameraSnapshotStrategyService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.common.basic.exception.Asserts;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;
import java.time.LocalDate;
import java.util.Objects;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

/**
 * <p>
 * 摄像头抓图策略表 服务实现类
 * </p>
 *
 * @author kinggu
 * @since 2025-10-10
 */
@Slf4j
@Service
public class HwCameraSnapshotStrategyServiceImpl extends ServiceImpl<HwCameraSnapshotStrategyMapper, HwCameraSnapshotStrategy> implements HwCameraSnapshotStrategyService {

    @Resource
    private HwCameraSnapshotRelationMapper snapshotRelationMapper;
    
    @Resource
    private HwCameraSnapshotTimeslotRelationMapper timeslotRelationMapper;
    
    @Resource
    private HwCameraTimeSlotMapper timeSlotMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HwCameraSnapshotStrategyVo create(HwCameraSnapshotStrategyCreateReqDTO createReqDTO) {
        HwCameraSnapshotStrategy entity = new HwCameraSnapshotStrategy();
        BeanUtils.copyProperties(createReqDTO, entity);
        
        // 如果设置为全局策略，需要先将其他策略设为非全局
        if (Boolean.TRUE.equals(entity.getGlobalDefault())) {
            clearOtherGlobalDefaultStrategies(null); // 创建时没有ID，传null
        }
        
        boolean success = save(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public  HwCameraSnapshotStrategyVo update(HwCameraSnapshotStrategyUpdateReqDTO updateReqDTO) {
        // 1. 校验待更新的记录是否存在
        if (getById(updateReqDTO.getId()) == null) {
            Asserts.fail("记录不存在，无法更新");
        }
        HwCameraSnapshotStrategy entity = new HwCameraSnapshotStrategy();
        BeanUtils.copyProperties(updateReqDTO, entity);
        
        // 2. 如果设置为全局策略，需要先将其他策略设为非全局
        if (Boolean.TRUE.equals(entity.getGlobalDefault())) {
            clearOtherGlobalDefaultStrategies(entity.getId());
        }
        
        boolean success = updateById(entity);
        if (success) {
            return getVOById(entity.getId());
        }
        return null;
    }

    @Override
    public CommonPage<HwCameraSnapshotStrategyVo> list(BasePageReqDTO pageReqDTO) {
        QueryWrapper<HwCameraSnapshotStrategy> queryWrapper = new QueryWrapper<>();

        // 排序
        if (StrUtil.isNotEmpty(pageReqDTO.getSortBy())) {
            // 注意：pageReqDTO.getSortBy() 需要是数据库中的列名（驼峰转下划线），请注意防护SQL注入
            if (Objects.equals(BasePageReqDTO.ORDER_DESC, pageReqDTO.getOrder())) {
                queryWrapper.orderByDesc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            } else {
                queryWrapper.orderByAsc(StrUtil.toUnderlineCase(pageReqDTO.getSortBy()));
            }
        }

        // 关键字模糊查询
        if (StrUtil.isNotEmpty(pageReqDTO.getKeyword())) {
            // TODO: 请根据业务需求，修改需要模糊查询的字段，以下为示例
            // queryWrapper.and(wrapper -> wrapper.like("name", pageReqDTO.getKeyword())
            //                                   .or()
            //                                   .like("description", pageReqDTO.getKeyword()));
        }
        
        // 根据 page 参数决定是否分页
        if (Boolean.TRUE.equals(pageReqDTO.getPage())) {
            Page<HwCameraSnapshotStrategy> page = new Page<>(pageReqDTO.getPageNum(), pageReqDTO.getPageSize());
            Page<HwCameraSnapshotStrategy> dbPage = baseMapper.selectPage(page, queryWrapper);
            IPage<HwCameraSnapshotStrategyVo> voPage = dbPage.convert(this::convertToVo);
            return CommonPage.restPage(voPage);
        } else {
            List<HwCameraSnapshotStrategy> allRecords = baseMapper.selectList(queryWrapper);
            CommonPage<HwCameraSnapshotStrategyVo> result = new CommonPage<>();
            result.setList(convertToVoList(allRecords));
            result.setTotal((long) allRecords.size());
            result.setPageNum(1);
            result.setPageSize(allRecords.size());
            result.setTotalPage(1);
            return result;
        }
    }

    @Override
    public HwCameraSnapshotStrategyVo getVOById(Long id) {
        HwCameraSnapshotStrategy entity = getById(id);
        return convertToVo(entity);
    }

    @Override
    public List<HwCameraSnapshotStrategyVo> convertToVoList(List<HwCameraSnapshotStrategy> entityList) {
        if (entityList == null) {
            return null;
        }
        return entityList.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }

    private HwCameraSnapshotStrategyVo convertToVo(HwCameraSnapshotStrategy entity) {
        if (entity == null) {
            return null;
        }
        HwCameraSnapshotStrategyVo vo = new HwCameraSnapshotStrategyVo();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    @Override
    public HwCameraSnapshotStrategy get(Long id) {
        return getById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        // 1. 校验待删除的记录是否存在
        if (getById(id) == null) {
            Asserts.fail("记录不存在，无法删除");
        }
        return removeById(id);
    }
    
    // ==================== 扩展业务方法实现 ====================
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setGlobalDefault(Long strategyId) {
        log.info("设置策略[{}]为全局默认策略", strategyId);
        
        try {
            // 1. 取消其他策略的全局默认标记
            baseMapper.update(null,
                new UpdateWrapper<HwCameraSnapshotStrategy>()
                    .set(HwCameraSnapshotStrategy.GlobalDefault, false)
                    .eq(HwCameraSnapshotStrategy.GlobalDefault, true)
            );
            
            // 2. 设置当前策略为全局默认
            HwCameraSnapshotStrategy strategy = getById(strategyId);
            if (strategy == null) {
                log.error("策略[{}]不存在", strategyId);
                return false;
            }
            
            strategy.setGlobalDefault(true);
            int updated = baseMapper.updateById(strategy);
            
            if (updated > 0) {
                log.info("设置全局默认策略成功");
                return true;
            } else {
                log.error("设置全局默认策略失败");
                return false;
            }
            
        } catch (Exception e) {
            log.error("设置全局默认策略异常", e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindCameraStrategy(Long cameraId, Long strategyId, 
                                      LocalDate effectiveDate, LocalDate expiryDate) {
        log.info("绑定摄像头[{}]到策略[{}]", cameraId, strategyId);
        
        try {
            // 检查是否已存在绑定
            HwCameraSnapshotRelation existing = snapshotRelationMapper.selectOne(
                new QueryWrapper<HwCameraSnapshotRelation>()
                    .eq(HwCameraSnapshotRelation.CameraId, cameraId)
                    .eq(HwCameraSnapshotRelation.Deleted, false)
            );
            
            if (existing != null) {
                // 更新现有绑定
                existing.setStrategyId(strategyId);
                existing.setEffectiveDate(effectiveDate);
                existing.setExpiryDate(expiryDate);
                snapshotRelationMapper.updateById(existing);
            } else {
                // 创建新绑定
                HwCameraSnapshotRelation relation = new HwCameraSnapshotRelation();
                relation.setCameraId(cameraId);
                relation.setStrategyId(strategyId);
                relation.setEffectiveDate(effectiveDate);
                relation.setExpiryDate(expiryDate);
                relation.setDeleted(false);
                snapshotRelationMapper.insert(relation);
            }
            
            log.info("绑定策略成功");
            return true;
            
        } catch (Exception e) {
            log.error("绑定策略异常", e);
            throw e;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbindCameraStrategy(Long cameraId) {
        log.info("解绑摄像头[{}]的策略", cameraId);
        
        try {
            int deleted = snapshotRelationMapper.delete(
                new QueryWrapper<HwCameraSnapshotRelation>()
                    .eq(HwCameraSnapshotRelation.CameraId, cameraId)
            );
            
            log.info("解绑策略成功，删除记录数: {}", deleted);
            return deleted > 0;
            
        } catch (Exception e) {
            log.error("解绑策略异常", e);
            throw e;
        }
    }
    
    @Override
    public List<Long> getBindCameraIds(Long strategyId) {
        return snapshotRelationMapper.selectCameraIdsByStrategyId(strategyId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean enableStrategy(Long strategyId) {
        log.info("启用策略[{}]", strategyId);
        
        HwCameraSnapshotStrategy strategy = getById(strategyId);
        if (strategy == null) {
            return false;
        }
        
        strategy.setStatus(true);
        return baseMapper.updateById(strategy) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean disableStrategy(Long strategyId) {
        log.info("禁用策略[{}]", strategyId);
        
        HwCameraSnapshotStrategy strategy = getById(strategyId);
        if (strategy == null) {
            return false;
        }
        
        strategy.setStatus(false);
        return baseMapper.updateById(strategy) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindTimeslots(StrategyTimeslotBindReqDTO bindReqDTO) {
        Long strategyId = bindReqDTO.getStrategyId();
        log.info("策略[{}]绑定时间段，数量: {}", strategyId, bindReqDTO.getTimeSlots().size());
        
        // 1. 验证策略是否存在
        if (getById(strategyId) == null) {
            Asserts.fail("策略不存在");
        }

        try {
            // 2. 先移除该策略的所有时间段绑定
            timeslotRelationMapper.delete(
                new QueryWrapper<HwCameraSnapshotTimeslotRelation>()
                    .eq(HwCameraSnapshotTimeslotRelation.StrategyId, strategyId)
            );

            // 3. 批量插入新的绑定关系
            for (StrategyTimeslotBindReqDTO.TimeSlotBindInfo timeSlotInfo : bindReqDTO.getTimeSlots()) {
                HwCameraSnapshotTimeslotRelation relation = new HwCameraSnapshotTimeslotRelation();
                relation.setStrategyId(strategyId);
                relation.setTimeSlotId(timeSlotInfo.getTimeSlotId());
                relation.setDeleted(false);
                timeslotRelationMapper.insert(relation);
            }
            
            log.info("策略[{}]绑定时间段成功", strategyId);
            return true;
        } catch (Exception e) {
            log.error("绑定时间段失败", e);
            throw new RuntimeException("绑定时间段失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean unbindTimeslots(StrategyTimeslotUnbindReqDTO unbindReqDTO) {
        Long strategyId = unbindReqDTO.getStrategyId();
        List<Long> timeSlotIds = unbindReqDTO.getTimeSlotIds();
        log.info("策略[{}]解绑时间段，数量: {}", strategyId, timeSlotIds.size());

        // 1. 验证策略是否存在
        if (getById(strategyId) == null) {
            Asserts.fail("策略不存在");
        }

        try {
            // 2. 批量删除关联关系
            int deleted = timeslotRelationMapper.delete(
                new QueryWrapper<HwCameraSnapshotTimeslotRelation>()
                    .eq(HwCameraSnapshotTimeslotRelation.StrategyId, strategyId)
                    .in(HwCameraSnapshotTimeslotRelation.TimeSlotId, timeSlotIds)
            );
            
            log.info("策略[{}]解绑时间段成功，删除记录数: {}", strategyId, deleted);
            return deleted > 0;
        } catch (Exception e) {
            log.error("解绑时间段失败", e);
            throw new RuntimeException("解绑时间段失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public List<HwCameraTimeSlotVo> getTimeslotsByStrategyId(Long strategyId) {
        // 1. 获取策略关联的时间段ID列表
        List<Long> timeSlotIds = timeslotRelationMapper.selectList(
            new QueryWrapper<HwCameraSnapshotTimeslotRelation>()
                .eq(HwCameraSnapshotTimeslotRelation.StrategyId, strategyId)
                .eq(HwCameraSnapshotTimeslotRelation.Deleted, false)
        ).stream()
         .map(HwCameraSnapshotTimeslotRelation::getTimeSlotId)
         .collect(Collectors.toList());

        if (timeSlotIds.isEmpty()) {
            return new ArrayList<>();
        }

        // 2. 根据时间段ID列表查询时间段信息（使用统一的时间段表）
        List<HwCameraTimeSlot> timeSlots = timeSlotMapper.selectList(
            new QueryWrapper<HwCameraTimeSlot>()
                .in(HwCameraTimeSlot.ID, timeSlotIds)
                .eq(HwCameraTimeSlot.Status, 1) // 只查询启用的时间段
        );

        // 3. 转换为VO
        return timeSlots.stream()
            .map(this::convertTimeSlotToVo)
            .collect(Collectors.toList());
    }
    
    /**
     * 将时间段实体转换为VO
     */
    private HwCameraTimeSlotVo convertTimeSlotToVo(HwCameraTimeSlot entity) {
        if (entity == null) {
            return null;
        }
        HwCameraTimeSlotVo vo = new HwCameraTimeSlotVo();
        BeanUtils.copyProperties(entity, vo);
        
        // 设置是否跨日
        vo.setCrossDay(entity.isCrossDay());
        
        return vo;
    }
    
    /**
     * 清除其他策略的全局默认标识
     * @param excludeId 要排除的策略ID（当前正在更新或创建的策略）
     */
    private void clearOtherGlobalDefaultStrategies(Long excludeId) {
        UpdateWrapper<HwCameraSnapshotStrategy> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq(HwCameraSnapshotStrategy.GlobalDefault, true)
                     .set(HwCameraSnapshotStrategy.GlobalDefault, false);
        
        // 如果是更新操作，排除当前策略自身
        if (excludeId != null) {
            updateWrapper.ne(HwCameraSnapshotStrategy.ID, excludeId);
        }
        
        baseMapper.update(null, updateWrapper);
        log.info("已清除其他抓图策略的全局默认标识，排除的策略ID: {}", excludeId);
    }
} 